package answercard;

import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.util.*;

/**
 * 答题卡识别
 * 1.切割图片最大轮廓
 * 2.根据切割好的轮廓图，再按百分比切割出选择题区域
 * 3.根据图像坐标解释答案
 * //TODO 获取答案算法还有待优化
 * @author chenkn
 * since 2018/12/18
 */
public class AnswerCard {
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    public static void main(String[] args) {
        Mat source = Imgcodecs.imread("D:\\eclipse_wk\\opencv-master\\img\\a8.jpg");
        process(source);
    }

    static void process(Mat source){
        Mat srcImage2 = new Mat();
        Mat srcImage3 = new Mat();
        Mat srcImage4 = new Mat();
        Mat srcImage5 = new Mat();

        Imgproc.cvtColor(source, srcImage2, Imgproc.COLOR_RGB2GRAY); //图片变成灰度图片,它将图像从一个颜色空间转换为另一个颜色空间。
        Imgproc.adaptiveThreshold(srcImage2, srcImage3, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY_INV, 41, 10);//图片二值化
        Imgcodecs.imwrite("D://ask//result3.jpg", srcImage3);

//			// 膨胀，连接边缘
        Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2*1+1, 2*1+1));
        Imgproc.erode(srcImage3, srcImage4, element);
        Imgproc.dilate(srcImage4, srcImage5, element);
        Imgcodecs.imwrite("D://ask//result4.jpg", srcImage3);

        Vector<MatOfPoint> chapter1 = new Vector<>();
        Vector<MatOfPoint> chapter2 = new Vector<>();
        Vector<MatOfPoint> chapter3 = new Vector<>();
        Imgproc.findContours(srcImage3, chapter1, new Mat(), 0, 2);//查找轮廓
        List<RectComp> rectCompList = new ArrayList<>();
        for (int i = 0; i < chapter1.size(); i++) {
            MatOfPoint matOfPoint = chapter1.get(i);
            Rect rm = Imgproc.boundingRect(matOfPoint);
            RectComp ti = new RectComp(rm);
            if (ti.rm.width > 500 && rm.height > 500) {
//                Mat maxMat = source.submat(new Rect(rm.x,rm.y,rm.width,rm.height));
                Mat maxMat = srcImage3.submat(new Rect(rm.x,rm.y,rm.width,rm.height));
                Imgproc.drawContours(source, chapter1, i, new Scalar(0,0,255), 1);
                Imgcodecs.imwrite("D://ask//i"+i+".jpg", maxMat);//获取选择题轮廓
                Imgproc.findContours(maxMat, chapter2, new Mat(), 1, 2);//查找轮廓
                System.out.println("maxMat = " + maxMat);
                Rect rect = new Rect(maxMat.width()/2+20,new Double(maxMat.height() * 0.096).intValue(),rm.width/2-100,new Double(rm.height * 0.264).intValue()-20);
                System.out.println("rect = " + rect);
                Mat answerImage = maxMat.submat(rect);
                System.out.println("answerImage = " + answerImage);
                Imgcodecs.imwrite("D://ask//"+i+"answerImage.jpg", answerImage);//获取选择题轮廓

                Imgproc.findContours(answerImage,chapter3,new Mat(),0,2);
                System.out.println("chapter3.size() = " + chapter3.size());
                for (int j = 0; j < chapter3.size(); j++) {
                    MatOfPoint matOfPoint3 = chapter3.get(j);
                    Rect rm3 = Imgproc.boundingRect(matOfPoint3);
                    RectComp ti3 = new RectComp(rm3);
                    //把轮廓宽度区间在 50 - 80 范围内的轮廓装进矩形集合
                    if (ti3.rm.area() > 3000 && rm3.width > 50) {
                        Mat mat = answerImage.submat(rm3);
                        Imgproc.drawContours(answerImage, chapter3, j, new Scalar(0, 0, 255), 3);
                        Imgcodecs.imwrite("D://ask//jjjj" + j + ".jpg", mat);
                        rectCompList.add(ti3);
                    }
                }

                System.out.println("chapter2.size() = " + chapter2.size());

            }
        }
        System.out.println("rectCompList.size() = " + rectCompList.size());
        rectCompList.sort(Comparator.naturalOrder());
        System.out.println("rectCompList = " + rectCompList);
        TreeMap<Integer,String> listenAnswer = new TreeMap<>();
        for (int i = 0; i < rectCompList.size(); i++) {
            RectComp rect = rectCompList.get(i);
            System.out.println("rect.getRm() = " + rect.getRm());
           /* Mat mat = source.submat(rect.rm);
            Imgproc.drawContours(source, chapter1, i, new Scalar(0,0,255), 3);
            Imgcodecs.imwrite("D://ask//"+i+".jpg", mat);*/
            if (rect.getRm().area() > 3000) {
                if (rect.getRm().x < 160) {
                    listenAnswer.put(i, "A");
                } else if ((rect.getRm().x > 160) && (rect.getRm().x < 220)) {
                    listenAnswer.put(i, "B");
                } else if ((rect.getRm().x > 200) && (rect.getRm().x < 350)) {
                    listenAnswer.put(i, "C");
                } else if (rect.getRm().x > 350) {
                    listenAnswer.put(i, "D");
                }
            } else {
                listenAnswer.put(i, "未填写");
            }
        }
        StringBuilder resultValue = new StringBuilder("最终结果：试题编号-答案 ");
        listenAnswer.keySet().forEach(key-> resultValue.append("【").append(key + 1).append(":").append(listenAnswer.get(key)).append("】"));
        System.out.println("resultValue = " + resultValue);
        System.exit(0);

    }
}
